#include "cFifo.h"

#define MAX(x, y)             ( ((x) > (y)) ? (x) : (y) ) 
#define MIN(x, y)             ( ((x) < (y)) ? (x) : (y) ) 

/*
*  Determine whether some value is a power of two, where zero is
* *not* considered a power of two.
*/
#define is_power_of_2(n)    ((n) != 0 && (((n) & ((n) - 1)) == 0))

/**
* FIFO_Init - allocates a new FIFO using a preallocated buffer
* @buffer: the size of the internal buffer, this have to be a power of 2.
* @size: the size of the internal buffer
*/
uint8_t FIFO_Init(fifo_t *fifo, unsigned char *buffer, unsigned long int size)
{
    /* size must be a power of 2 */
	assert_param(is_power_of_2(size));
    fifo->buffer = buffer;
    fifo->size = size;
    fifo->in = 0;
    fifo->out = 0;
    return 0;
}

/**
* __fifo_putc - put a data into the FIFO, no locking version
* @fifo: the fifo to be used.
* @c: the data to be added.
*/
uint8_t FIFO_Putc(fifo_t *fifo, unsigned char c)
{
    /* if there is free space*/
    if((fifo->size - fifo->in + fifo->out) > 0)
    {    
        *(fifo->buffer + (fifo->in & (fifo->size - 1))) = c;
        fifo->in += 1;
        return 1;
    }

    return 0;
}

/**
* FIFO_Getc - get adata from the FIFO, no locking version
* @fifo: the fifo to be used.
* @c: where the data must be copied.
*/
uint8_t FIFO_Getc(fifo_t *fifo, unsigned char *c)
{
    if((fifo->in - fifo->out) > 0)
    {
        *c = *(fifo->buffer + (fifo->out & (fifo->size - 1)));
        fifo->out += 1;
        return 1;
    }

    return 0;
}

/**
* FIFO_Length - returns the number of bytes available in the FIFO, no locking version
* @fifo: the fifo to be used.
*/
unsigned long int FIFO_Length(fifo_t *fifo)
{
    return fifo->in - fifo->out;
}

/**
* FIFO_Reset - removes the entire FIFO contents, no locking version
* @fifo: the fifo to be emptied.
*/
void FIFO_Reset(fifo_t *fifo)
{
    fifo->in = fifo->out = 0;
}

/**
*/
void FIFO_Dropc(fifo_t *fifo, unsigned long int dorp_bytes)
{
        if ((fifo->in - fifo->out) >= (dorp_bytes & (fifo->size - 1)))
        {
                fifo->out += dorp_bytes & (fifo->size - 1);
        }
}
